#pragma once

#include <algorithm>


namespace rt
{

	struct Color
	{
		Color(float r = 0.0f, float g = 0.0f, float b = 0.0f, float a = 0.0f)
			:R(r), G(g), B(b), A(a)
		{}

		float R,G,B,A;

		inline void zero()
		{
			R = 0.0f;
			G = 0.0f;
			B = 0.0f;
			A = 0.0f;
		}

		inline void operator += (const Color & c)
		{
			R += c.R;
			G += c.G;
			B += c.B;
			A += c.A;
		}

		/*
		 * WARNING: may lead to some components being less than 0, which is not corrected even if you use
		 * normalize() or normalizeAndScale() (due to performance reasons).
		 */
		inline void operator -= (const Color & c)
		{
			R -= c.R;
			G -= c.G;
			B -= c.B;
			A -= c.A;
		}

		inline void operator *= (float scalar)
		{
			R = R * scalar;
			G = G * scalar;
			B = B * scalar;
			A = A * scalar;
		}

		inline void normalize()
		{
			R = min(1.0f, R);
			G = min(1.0f, G);
			B = min(1.0f, B);
			A = min(1.0f, A);
		}

		inline void normalizeAndScale(float scale)
		{
			R = scale * min(1.0f, R);
			G = scale * min(1.0f, G);
			B = scale * min(1.0f, B);
			A = scale * min(1.0f, A);
		}

		static Color BLACK;
		static Color WHITE;
		static Color RED;
		static Color GREY;
	};


	inline Color operator + (const Color & c1, const Color & c2)
	{
		return Color(
			c1.R + c2.R,
			c1.G + c2.G,
			c1.B + c2.B,
			c1.A + c2.A);
	}

	/*
	 * WARNING: may lead to some components being less than 0, which is not corrected even if you use
	 * normalize() or normalizeAndScale() (due to performance reasons).
	 */
	inline Color operator - (const Color & c1, const Color & c2)
	{
		return Color(
			c1.R - c2.R,
			c1.G - c2.G,
			c1.B - c2.B,
			c1.A - c2.A);
	}

	inline Color operator * (const Color & c1, const Color & c2)
	{
		return Color(
			c1.R * c2.R,
			c1.G * c2.G,
			c1.B * c2.B,
			c1.A * c2.A);
	}

	inline Color operator * (const Color & c1, float scalar)
	{
		return Color(
			c1.R * scalar,
			c1.G * scalar,
			c1.B * scalar,
			c1.A * scalar);
	}

	inline Color operator * (float scalar, const Color & c1)
	{
		return Color(
			c1.R * scalar,
			c1.G * scalar,
			c1.B * scalar,
			c1.A * scalar);
	}
}
